package com.uhu.tag.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.uhu.common.UtagConstant;
import com.uhu.exception.BusinessException;
import com.uhu.redis.RedisKeyConstant;
import com.uhu.tag.dao.TagGroupMapper;
import com.uhu.tag.dto.req.TagGroupSaveReqDTO;
import com.uhu.tag.dto.req.TagGroupUpdateReqDTO;
import com.uhu.tag.dto.res.TagGroupListByCategoryIdResDTO;
import com.uhu.tag.entity.Tag;
import com.uhu.tag.entity.TagGroup;
import com.uhu.tag.service.ITagGroupService;
import com.uhu.tag.service.ITagService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * <p>
 * 标签组表 服务实现类
 * </p>
 *
 * @author liujunjie
 * @since 2023-12-01
 */
@Slf4j
@Service
public class TagGroupServiceImpl extends ServiceImpl<TagGroupMapper, TagGroup> implements ITagGroupService {

    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private ITagService iTagService;

    @Override
    public List<TagGroupListByCategoryIdResDTO> tagGroupListQueryByCategoryId(Long tagCategoryId) {
        List<TagGroup> tagGroups = list(new QueryWrapper<TagGroup>()
                .eq("tag_category_id", tagCategoryId)
                .orderByAsc("sort_id")
        );
        return BeanUtil.copyToList(tagGroups, TagGroupListByCategoryIdResDTO.class);
    }

    @Override
    public void saveTagGroup(TagGroupSaveReqDTO tagGroupSaveReqDTO) {
        RLock rLock = redissonClient.getLock(RedisKeyConstant.TAG_GROUP_EDIT_LOCK);
        if (!rLock.tryLock()) {
            throw new BusinessException(UtagConstant.GET_LOCK_FAIL);
        }

        try {
            TagGroup tagGroup = getOne(new QueryWrapper<TagGroup>()
                    .eq("tag_category_id", tagGroupSaveReqDTO.getTagCategoryId())
                    .orderByAsc("sort_id").last("limit 1"));
            Integer lastSortId = 0;
            if (tagGroup != null) {
                lastSortId = tagGroup.getSortId() + 1;
            }
            TagGroup saveTagGroup = BeanUtil.copyProperties(tagGroupSaveReqDTO, TagGroup.class);
            saveTagGroup.setSortId(lastSortId);
            saveOrUpdate(tagGroup);
        } finally {
            rLock.unlock();
        }
    }

    @Override
    public void updateTagGroup(TagGroupUpdateReqDTO tagGroupUpdateReqDTO) {
        RLock rLock = redissonClient.getLock(RedisKeyConstant.TAG_GROUP_EDIT_LOCK);
        if (!rLock.tryLock()) {
            throw new BusinessException(UtagConstant.GET_LOCK_FAIL);
        }

        try {
            long count = count(new QueryWrapper<TagGroup>().eq("tag_group_id", tagGroupUpdateReqDTO.getTagGroupId()));
            if (count < 1) {
                throw new BusinessException("标签组不存在");
            }
            saveOrUpdate(BeanUtil.copyProperties(tagGroupUpdateReqDTO, TagGroup.class));
        } finally {
            rLock.unlock();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sortTagGroup(Long[] ids, Long tagCategoryId) {
        RLock rLock = redissonClient.getLock(RedisKeyConstant.TAG_GROUP_EDIT_LOCK);
        if (!rLock.tryLock()) {
            throw new BusinessException(UtagConstant.GET_LOCK_FAIL);
        }

        try {
            // 统计标签大类下标签组数
            long count = count(new QueryWrapper<TagGroup>()
                    .eq("tag_category_id", tagCategoryId)
                    .in("tag_group_id", ids)
            );
            if (count != ids.length) {
                log.error("sortTagGroup ids.length != database.size, please check it");
                throw new BusinessException(UtagConstant.SYSTEM_ERROR);
            }
            for (int i = 0; i < ids.length; i++) {
                TagGroup tagGroup = new TagGroup();
                tagGroup.setTagGroupId(ids[i]);
                tagGroup.setTagCategoryId(tagCategoryId);
                tagGroup.setSortId(i);
                updateById(tagGroup);
            }
        } finally {
            rLock.unlock();
        }
    }

    @Override
    public void deleteTagGroup(Long tagGroupId) {
        RLock rLock = redissonClient.getLock(RedisKeyConstant.TAG_GROUP_EDIT_LOCK);
        if (!rLock.tryLock()) {
            throw new BusinessException(UtagConstant.GET_LOCK_FAIL);
        }

        try {
            Long size = count(new QueryWrapper<TagGroup>()
                    .eq("tag_group_id", tagGroupId)
                    .last("limit 1")
            );
            if (size < 1) {
                log.error("deleteTagGroup groupId = {} not found", tagGroupId);
                throw new BusinessException(UtagConstant.SYSTEM_ERROR);
            }

            Long childSize = iTagService.count(new QueryWrapper<Tag>()
                    .eq("tag_group_id", tagGroupId)
                    .last("limit 1")
            );
            if (childSize > 0) {
                throw new BusinessException("当前标签组下已存在标签，无法删除！！！");
            }

            removeById(tagGroupId);
        } finally {
            rLock.unlock();
        }
    }
}
